package com.nj9you.sdk.utils;

import android.util.Base64;

import com.nj9you.sdk.constant.Constants;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AlipayHelper {
    private static final String ALGORITHM = "RSA";
    private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
    private static final String DEFAULT_CHARSET = "UTF-8";
    private static final String PARTNER = "2088421556399831";
    private static final String SELLER = "nanjing_9you@foxmail.com";
    private static final String RSA_PRIVATE =
            "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMmXDSy6mPq285UD"
                    + "RJPAVJJM7t4Wqp9gnXbpDatnmvdxwHLycB42pVuMdAR9pESkzF85HaaeL5XCrEp/"
                    + "olsn9zpDSY+hp9daL09QseVmrZGewy10XPhZtocAYHHNroNNnwKr+vesSIOqLUfr"
                    + "IC5abVD1iMtxRVkhkZaHkY6t4+exAgMBAAECgYBOzzu6UdS+p0mA5v8nWBh3/ZWg"
                    + "w3G+zxGgTCoo6V8e/5yCE5+bYDezG6y7mLbgkyDG1VhvLAZkYO/kTBOX2X7/2Wxr"
                    + "WA5557uNPZSRNpwzKrG28pkdcD5gLhNQUfcAj5gafITwT/YJBeDlQ64v0vahWP7X"
                    + "nIp7llgBz00mirQTNQJBAOZVfRD3gxktx2wRLEf0YAKNdil9uiqZShu+oPUL8yD2"
                    + "M2qPwUL9K70/3DNuO42IBzBKpTNCuYcMOrzEwfhFOE8CQQDgDZ0oIFj86tHZ4Omb"
                    + "xEbkz7u0qiVmmb3SpFRs7h2usjN6I1VMBlw2fObSIQCWanIhkKz1OBF97a5ziC//"
                    + "3N//AkEAlYNWnKXd3oE92uNG2CpEDEQhOIuZRb+dQGc8efRYzMOj2n8YF1DZjI4g"
                    + "dO4QEC4FZI5/r8eXQJdqpVAfDPZ5twJAQQASGOMRjgZ97QzQGS2fN6CAn1BBW3u8"
                    + "01BzYcrO97ChOIzpoQ2zUOd5e3qxlfG5vL0hQF8MzBDZbJEVA9DLdwJBAId482HK"
                    + "K7j9vgq1OINImXkdkzjkz96EF1qdNWfJ5G92Mb5FZ6xXTHSBXYGINvaTRtqebZDE"
                    + "iMvznz0mcRsmGeo=";

    public static String sign(String content, String privateKey) {
        try {
            PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
                    Base64.decode(privateKey, Base64.DEFAULT));
            KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);

            java.security.Signature signature = java.security.Signature
                    .getInstance(SIGN_ALGORITHMS);

            signature.initSign(priKey);
            signature.update(content.getBytes(DEFAULT_CHARSET));

            byte[] signed = signature.sign();
            return Base64.encodeToString(signed, Base64.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /*****************************************************/

    public static String getSignedOrderInfo(String price, String subject, String body, String orderId, String attach) {
        Map<String, String> map = buildOrderParamMap(price, subject, body, orderId, attach);
        String unsignedOrderInfo = buildOrderParam(map);
        return unsignedOrderInfo + "&" + getSign(map, RSA_PRIVATE);
    }

    private static String buildOrderParam(Map<String, String> map) {
        List<String> keys = new ArrayList<String>(map.keySet());

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < keys.size() - 1; i++) {
            String key = keys.get(i);
            String value = map.get(key);
            sb.append(buildKeyValue(key, value, true));
            sb.append("&");
        }

        String tailKey = keys.get(keys.size() - 1);
        String tailValue = map.get(tailKey);
        sb.append(buildKeyValue(tailKey, tailValue, true));

        return sb.toString();
    }

    private static String getSign(Map<String, String> map, String rsaKey) {
        List<String> keys = new ArrayList<String>(map.keySet());
        // key排序
        Collections.sort(keys);

        StringBuilder authInfo = new StringBuilder();
        for (int i = 0; i < keys.size() - 1; i++) {
            String key = keys.get(i);
            String value = map.get(key);
            authInfo.append(buildKeyValue(key, value, false));
            authInfo.append("&");
        }

        String tailKey = keys.get(keys.size() - 1);
        String tailValue = map.get(tailKey);
        authInfo.append(buildKeyValue(tailKey, tailValue, false));

        String oriSign = AlipayHelper.sign(authInfo.toString(), rsaKey);
        String encodedSign = "";

        try {
            encodedSign = URLEncoder.encode(oriSign, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "sign=" + encodedSign;
    }

    private static String buildKeyValue(String key, String value, boolean isEncode) {
        StringBuilder sb = new StringBuilder();
        sb.append(key);
        sb.append("=");
        if (isEncode) {
            try {
                sb.append(URLEncoder.encode(value, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                sb.append(value);
            }
        } else {
            sb.append(value);
        }
        return sb.toString();
    }

    private static Map<String, String> buildOrderParamMap(String price, String subject, String body, String orderId, String attach) {
        String rmbPrice = Utils.convertFenToYuan(price);
        Map<String, String> keyValues = new HashMap<String, String>();
        keyValues.put("app_id", "2016082601806646");
        keyValues.put("biz_content",
                "{"
                        + "\"timeout_express\":\"30m\","
                        + "\"product_code\":\"QUICK_MSECURITY_PAY\","
                        + "\"total_amount\":\"" + rmbPrice + "\","
                        + "\"subject\":\"" + subject + "\","
                        + "\"body\":\"" + body + "\","
                        + "\"passback_params\":\"" + attach + "\","
                        + "\"out_trade_no\":\"" + orderId + "\""
                        + "}"
        );
        keyValues.put("charset", "utf-8");
        keyValues.put("method", "alipay.trade.app.pay");
        keyValues.put("sign_type", "RSA");
        keyValues.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        keyValues.put("version", "1.0");
        keyValues.put("notify_url", Constants.ALIPAY_NOTIFY_URL);
        return keyValues;
    }
}